package se.webbzon.boltzmann.battle.strategy.playerstrategy;

import java.awt.Color;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.List;

import se.webbzon.boltzmann.input.Button;
import se.webbzon.boltzmann.inventory.Inventory;
import se.webbzon.boltzmann.item.AbstractItem;
import se.webbzon.boltzmann.player.Player;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;

public class PSItemPage extends AbstractPSPage {
	
	// The phase difference for each step
	private static final double dt = Math.PI/15;
	
	// The amplitude of the arrow oscillation
	private static final double amplitude = 4;
	
	// The layout of the player strategy item page
	private final PSItemPageLayout layout;
	
	// A list of all the available items
	private final List<AbstractItem> items;
	
	// The phase of the arrow oscillation
	private volatile double t;
	
	// The y position of the up and down arrow
	private volatile int arrowY; 
	
	// The offset of the item frame (the index of the first visible item)
	private volatile int offset;
	
	// The index of the selected item
	private volatile int itemIndex;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public PSItemPage(	AbstractPSPage parent, 
									PSItemPageLayout layout,
									Player player) {
		super(parent);
		this.layout = layout;
		items = new ArrayList<AbstractItem>();
		Inventory inventory = player.getInventory();
		for (int row = 0; row < inventory.getRows(); row++) {
			for (int column = 0; column < inventory.getColumns(); column++) {
				AbstractItem item = inventory.getItem(row, column);
				if (item != null && item.isBattleItem())
					items.add(item);
			}
		}
		offset = 0;
		itemIndex = 0;
		t = 0;
		arrowY = 0;
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the number of items in this item page. **/
	public int items() {
		return items.size();
	}

	@Override public void onSelect(PlayerStrategyHud psh) {
		AbstractItem item = items.get(itemIndex);
		PSTargetPage targetPage = 
				new PSTargetPage(this,item.getBattleActionFactory(),psh);
		psh.setPage(targetPage);
	}

	@Override public void onReturn(PlayerStrategyHud psh) {
		psh.setPage(getParent());
	}

	@Override public void onPress(PlayerStrategyHud psh, Button button) {
		if (button == Button.DOWN) {
			// Next item
			if (itemIndex == items.size()-1) {
				itemIndex = 0;
			} else {
				itemIndex++;
			}
			if (!withinFrame(itemIndex))
				scrollFrame(itemIndex,false);
			
		} else if (button == Button.UP) {
			// Previous item
			if (itemIndex == 0) {
				itemIndex = items.size()-1;
			} else
				itemIndex--;
			if (!withinFrame(itemIndex))
				scrollFrame(itemIndex,true);
			
		} else if (button == Button.NEXT_ITEM) {
			// Scroll down
			if (itemIndex >= items.size()-6)
				itemIndex = items.size()-1;
			else
				itemIndex+=5;
			if (!withinFrame(itemIndex))
				scrollFrame(itemIndex,false);
			
		} else if (button == Button.PREVIOUS_ITEM) {
			// Scroll up
			if (itemIndex <= 5)
				itemIndex = 0;
			else
				itemIndex-=5;
			if (!withinFrame(itemIndex))
				scrollFrame(itemIndex,true);
		}
	}

	@Override public void onStep(PlayerStrategyHud psh) {
		t += dt;
		arrowY = (int) (amplitude * Math.sin(t));
	}

	@Override public void onDraw(PlayerStrategyHud psh, WorldCameraPane hud) {
		// Retrieve layout coefficients
		final int 	bx = layout.getXOffset(),
					by = layout.getYOffset();
		final int	xs = bx + layout.getItemXOffset(),
					ys = by + layout.getItemYOffset();
		final int	itemWidth = layout.getItemWidth(),
					itemHeight = layout.getItemHeight();
		final int	iconX = xs + layout.getIconXOffset(),
					iconY = layout.getIconYOffset();
		final int	iconWidth = layout.getIconWidth();
		final int	textY = iconY + layout.getTextYOffset(),
					textX = iconX + iconWidth + layout.getTextXSpacing();
		
		// Draw background
		hud.drawImage(layout.getBackground(), bx, by);
		
		final int last = Math.min(items() - offset,layout.getItems());
		for (int i = 0; i < last; i++) {
			// Draw each item
			AbstractItem item = items.get(i + offset);
			final int y = ys + i * itemHeight;
			
			if (itemIndex == i + offset) {
				// Draw white background if item is selected
				hud.setTransparency(0.5f);
				hud.setColor(Color.white);
				hud.fillRect(xs, y, itemWidth, itemHeight);
				hud.setTransparency(1);
			}

			hud.drawImage(	item.getTextureSet().get(0).getImage(), 
							iconX,
							y + iconY);
			hud.setFont(layout.getTextFont());
			hud.setColor(Color.black);
			hud.drawString(item.getName(), textX, y + textY);
			hud.setColor(Color.white);
			hud.drawString(item.getName(), textX - 1, y + textY - 1);
		}
		
		final ImageObserver o = hud.getImageObserver();
		final int 	bw = layout.getBackground().getWidth(o),
					bh = layout.getBackground().getHeight(o);
		final int	aw = layout.getUpArrow().getWidth(o),
					ah = layout.getUpArrow().getHeight(o);
		final int	ax = bx + (bw - aw)/2,
					ay = by - ah/2;
		 
		if (offset > 0)
			hud.drawImage(layout.getUpArrow(), ax, ay + arrowY);
		if (items() > offset + layout.getItems())
			hud.drawImage(layout.getDownArrow(), ax, ay + bh - arrowY);
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Returns true if the given index is within the frame of this
	 * item list. **/
	public final boolean withinFrame(int index) {
		return (index >= offset && index < offset + layout.getItems());
	}
	
	/** Scrolls the item list to the given index. (index must be between 0
	 * and items()-1). If the parameter "top" is set then the frame offset 
	 * will be moved so that the top of the frame is as close to the 
	 * selected index as possible. If the parameter "top" is clear then 
	 * the frame offset will be moved so that the bottom of the frame is 
	 * as close to the selected index as possible. **/
	private final void scrollFrame(int index, boolean top) {
		final int itemsPerFrame = layout.getItems();
		if (top)
			offset = (index + itemsPerFrame <= items()) ? index : index - itemsPerFrame + 1;
		else
			offset = (itemsPerFrame <= items() && index >= itemsPerFrame) ? 
						index - itemsPerFrame + 1 : 0; 
	}

}
